package com.catazzz.springbootstudy.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @作者: Tao
 * @日期: 2025/1/7
 * @时间: 14:15
 * @描述: Redis配置类 <br><pre>
 */
//@Configuration
public class RedisConfig {

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }

    /**
     * 配置并返回一个RedisTemplate实例
     * 该实例用于与Redis数据库进行交互和操作，通过此方法可以统一设置
     * RedisTemplate的序列化方式和连接工厂
     *
     * @param redisConnectionFactory Redis连接工厂，用于创建和管理Redis连接
     * @return 配置好的RedisTemplate实例，用于执行各种Redis操作
     */
    @Bean

    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 创建RedisTemplate实例
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 创建StringRedisSerializer实例，用于Redis键值的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 设置RedisTemplate的键序列化器
        redisTemplate.setKeySerializer(stringRedisSerializer);

        // 设置RedisTemplate的连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 设置RedisTemplate的值序列化器
        redisTemplate.setValueSerializer(stringRedisSerializer);

        // 设置RedisTemplate的哈希键序列化器
        redisTemplate.setHashKeySerializer(serializer());

        // 返回配置好的RedisTemplate实例
        return redisTemplate;
    }

    /**
     * 创建并配置一个Jackson2JsonRedisSerializer实例<br>
     * 该实例用于Redis操作中的序列化和反序列化过程<br>
     * 选择Object类作为泛型参数以支持序列化所有类型的对象
     *
     * @return 配置好的Jackson2JsonRedisSerializer实例
     */
    private Jackson2JsonRedisSerializer<Object> serializer() {
        // 实例化Jackson2JsonRedisSerializer
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);

        // 创建ObjectMapper实例，用于JSON序列化和反序列化
        ObjectMapper objectMapper = new ObjectMapper();

        // 设置对象属性的可见性，确保所有属性均可被序列化和反序列化
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        // 激活默认类型检测，允许处理非final类型的子类
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

        // 将配置好的ObjectMapper设置到序列化器
        serializer.setObjectMapper(objectMapper);

        // 返回配置好的序列化器实例
        return serializer;
    }

    /**
     * 创建并配置Redis连接工厂
     * 此方法使用Lettuce库配置并返回一个RedisConnectionFactory实例
     * Lettuce是一个可伸缩的线程安全的Redis客户端，适用于高性能的环境中
     *
     * @return RedisConnectionFactory 配置好的Redis连接工厂实例
     */
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        // 创建 RedisStandaloneConfiguration 实例并设置主机名和端口
        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration("localhost", 6379);

        // 创建 LettuceClientConfiguration 实例（可根据需要进一步配置）
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder().build();

        // 使用配置创建 LettuceConnectionFactory 实例
        return new LettuceConnectionFactory(standaloneConfig, clientConfig);
    }

}

